package com.caifeng.security;

import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import com.caifeng.domain.ResponseCode;
import com.caifeng.domain.ResponseResult;
import com.caifeng.domain.ServiceException;
import com.caifeng.domain.vo.DefaultVO;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.List;

@Component
public class SecurityFilter extends OncePerRequestFilter {

    @Value("${jwt.secret}")
    private String secret;

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,
                                    @NonNull HttpServletResponse response,
                                    @NonNull FilterChain filterChain) throws ServletException, IOException {

        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        if (!request.getServletPath().startsWith("/auth")) {
            String token = request.getHeader("Authorization");
            if (token == null || !JWTUtil.verify(token, secret.getBytes())) {
                ResponseResult result = new ResponseResult(ResponseCode.TOKEN_INVALIDATION, DefaultVO.of("token失效"));
                response.getWriter().write(JSONUtil.toJsonStr(result));
                return;
            }
            JWT jwt;
            try {
                jwt = JWTUtil.parseToken(token);
                JWTValidator.of(jwt).validateDate();
            } catch (ValidateException e) {
                ResponseResult result = new ResponseResult(ResponseCode.TOKEN_INVALIDATION, DefaultVO.of("token过期"));
                response.getWriter().write(JSONUtil.toJsonStr(result));
                return;
            }
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                    Long.parseLong(String.valueOf(jwt.getPayload("user_id"))),
                    token,
                    AuthorityUtils.createAuthorityList(List.of(String.valueOf(jwt.getPayload("permissions")).split(","))));
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        filterChain.doFilter(request, response);
    }
}